package manage

import (
	"regexp"

	"github.com/dgrijalva/jwt-go"
	"github.com/gofiber/fiber/v2"
	logger "github.com/sirupsen/logrus"

	"publish-manage/internal/domain"
	"publish-manage/internal/model"
	"publish-manage/internal/service"
	"publish-manage/pkg/constant"
	coreDomain "publish-manage/pkg/domain"
	"publish-manage/pkg/server"
)

var UserController = new(userController)

type userController struct{}

func (_ *userController) SignIn(ctx *fiber.Ctx) error {
	li := domain.LoginRequest{}
	if err := ctx.BodyParser(&li); err != nil {
		logger.Error(err)
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorParamParse,
			Msg:  "登录参数解析失败!",
		})
	}

	// 用户名密码方式登录
	_, token, err := service.UserService.Login(&model.User{Username: li.Username, Password: li.Password})
	if err != nil {
		logger.Error(err)
		return ctx.JSON(coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorInternal,
			Msg:  "服务出现异常",
		})
	}

	if token == "" {
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorDataNotMatch,
			Msg:  "登录失败",
		})
	}

	return ctx.JSON(&coreDomain.CommonResponse{
		Data: token,
	})
}

func (_ *userController) UpdatePassword(ctx *fiber.Ctx) error {
	upi := domain.UpdatePasswordRequest{}
	if err := ctx.BodyParser(&upi); err != nil {
		logger.Error(err)
		return ctx.JSON(coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorParamParse,
			Msg:  "参数解析失败",
		})
	}
	if upi.Id == "" {
		// 从jwt获取用户信息
		jwtToken := ctx.Locals(constant.JWT_CONTEXT).(*jwt.Token)
		claims := jwtToken.Claims.(jwt.MapClaims)
		upi.Id = claims["uid"].(string)
	}

	isStrong := PasswordStrengthCheck(8, 50, 4, upi.NewPassword)
	if !isStrong {
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorUnsupported,
			Msg:  "密码强度不够，必须大于8位的数字、大小写字母、特殊字符组合",
		})
	}

	if updated, err := service.UserService.UpdatePassword(&model.User{
		Id:       upi.Id,
		Password: upi.Password,
	}, upi.NewPassword); err != nil {
		logger.Error(err)
		return ctx.JSON(coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorInternal,
			Msg:  "新密码保存失败",
		})
	} else {
		if updated {
			return ctx.JSON(coreDomain.CommonResponse{})
		} else {
			return ctx.JSON(coreDomain.CommonResponse{
				Code: constant.ResponseCodeErrorDataNotMatch,
				Msg:  "原密码不匹配，无法更新密码",
			})
		}
	}
}

func (_ *userController) ResetPassword(ctx *fiber.Ctx) error {
	upi := domain.UpdatePasswordRequest{}
	if err := ctx.BodyParser(&upi); err != nil {
		logger.Error(err)
		return ctx.JSON(coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorParamParse,
			Msg:  "参数解析失败",
		})
	}
	if upi.Id == "" {
		return ctx.JSON(coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorParamRequired,
			Msg:  "用户ID不能为空",
		})
	}

	isStrong := PasswordStrengthCheck(8, 50, 4, upi.NewPassword)
	if !isStrong {
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorUnsupported,
			Msg:  "密码强度不够，必须大于8位的数字、大小写字母、特殊字符组合",
		})
	}

	if updated, err := service.UserService.ResetPassword(upi.Id, upi.NewPassword); err != nil {
		logger.Error(err)
		return ctx.JSON(coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorInternal,
			Msg:  "新密码保存失败",
		})
	} else {
		if updated {
			return ctx.JSON(coreDomain.CommonResponse{})
		} else {
			return ctx.JSON(coreDomain.CommonResponse{
				Code: constant.ResponseCodeErrorInternal,
				Msg:  "密码重置失败",
			})
		}
	}
}

func (_ *userController) Detail(ctx *fiber.Ctx) error {
	instance := new(model.User)
	var err error
	if err = ctx.QueryParser(instance); err != nil {
		logger.Error(err)
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorParamParse,
			Msg:  "参数解析失败!",
		})
	}
	if instance.Id == "" {
		// 从jwt获取用户信息
		jwtToken := ctx.Locals(constant.JWT_CONTEXT).(*jwt.Token)
		claims := jwtToken.Claims.(jwt.MapClaims)
		instance.Id = claims["uid"].(string)
	}

	instance, err = service.UserService.Get(instance)
	if err != nil {
		logger.Error(err)
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorInternal,
			Msg:  "获取用户详情失败",
		})
	}

	return ctx.JSON(&coreDomain.CommonResponse{
		Data: instance,
	})
}

func (_ *userController) Update(ctx *fiber.Ctx) error {
	instance := new(model.User)
	if err := ctx.BodyParser(instance); err != nil {
		logger.Error(err)
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorParamParse,
			Msg:  "参数解析失败!",
		})
	}
	if instance.Id == "" {
		// 从jwt获取用户信息
		jwtToken := ctx.Locals(constant.JWT_CONTEXT).(*jwt.Token)
		claims := jwtToken.Claims.(jwt.MapClaims)
		instance.Id = claims["uid"].(string)
	}

	if err := service.UserService.Update(instance); err != nil {
		logger.Error(err)
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorInternal,
			Msg:  "更新用户详情失败",
		})
	}
	return ctx.JSON(&coreDomain.CommonResponse{})
}

func (_ *userController) Add(ctx *fiber.Ctx) error {
	instance := new(model.User)
	if err := ctx.BodyParser(instance); err != nil {
		logger.Error(err)
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorParamParse,
			Msg:  "参数解析失败!",
		})
	}

	// 处理必填
	if instance.Username == "" || instance.Password == "" {
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorParamRequired,
			Msg:  "用户名/密码必须提供",
		})
	}

	isStrong := PasswordStrengthCheck(8, 50, 4, instance.Password)
	if !isStrong {
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorUnsupported,
			Msg:  "密码强度不够，必须大于8位的数字、大小写字母、特殊字符组合",
		})
	}

	duplicated, err := service.UserService.Add(instance)
	if err != nil {
		logger.Error(err)
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorInternal,
			Msg:  "服务出现异常",
		})
	}
	if duplicated {
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorDataExists,
			Msg:  "有重复记录",
		})
	}
	return ctx.JSON(&coreDomain.CommonResponse{Data: instance})
}

func (_ *userController) Delete(ctx *fiber.Ctx) error {
	instance := new(model.User)
	if err := ctx.QueryParser(instance); err != nil {
		logger.Error(err)
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorParamParse,
			Msg:  "参数解析失败!",
		})
	}
	if instance.Id == "" {
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorParamRequired,
			Msg:  "ID必须提供",
		})
	}
	err := service.UserService.Delete(instance.Id)
	if err != nil {
		logger.Error(err)
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorInternal,
			Msg:  "服务出现异常",
		})
	}
	return ctx.JSON(&coreDomain.CommonResponse{})
}

//List GET
func (c *userController) List(ctx *fiber.Ctx) error {
	condition := new(model.User)
	if err := ctx.QueryParser(condition); err != nil {
		logger.Error(err)
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorParamParse,
			Msg:  "参数解析失败!",
		})
	}
	limit, offset, orderBy, err := server.ParsePaginationInfoFromQuery(ctx)
	if err != nil {
		logger.Error(err)
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorParamParse,
			Msg:  "参数解析失败!",
		})
	}

	pi, err := service.UserService.List(condition, limit, offset, orderBy)
	if err != nil {
		logger.Error(err)
		return ctx.JSON(&coreDomain.CommonResponse{
			Code: constant.ResponseCodeErrorInternal,
			Msg:  "服务出现异常",
		})
	}
	return ctx.JSON(&coreDomain.CommonResponse{Data: pi})
}

// PasswordStrengthCheck 校验密码强度，5个级别，0最低，4最高
func PasswordStrengthCheck(min, max, level int, pwd string) bool {
	if len(pwd) < min {
		return false
	}
	if len(pwd) > max {
		return false
	}
	l := 0
	patternList := []string{`[0-9]+`, `[a-z]+`, `[A-Z]+`, `[~!@#$%^&*?_-]+`}
	for _, pattern := range patternList {
		match, _ := regexp.MatchString(pattern, pwd)
		if match {
			l++
		}
	}
	return l >= level
}
